#include "calculator.h"
#include "./ui_calculator.h"

Calculator::Calculator(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Calculator)
{
    ui->setupUi(this);
    building();
    LightTheme();
    connecting();
    setup();
}

Calculator::~Calculator()
{
    delete ui;
}

void Calculator::building()
{
    QFont fontButton("Times", 15);
    QFont fontLabel("Times", 20);

    gridlayout = new QGridLayout(this);

    Menu = new QPushButton("≡");
    Menu->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    Menu->setFont(fontButton);

    Menu->setFixedSize(30, 30);
    gridlayout->addWidget(Menu, 0, 0, 1, 1);

    MenuFromButton = new QMenu;
    themeMenu = new QAction(tr("Theme"));
    lightAction = new QAction(tr("Light"));
    lightAction->setData(1);
    darkAction = new QAction(tr("Dark"));
    darkAction->setData(2);
    MenuFromButton->addAction(themeMenu);

    closeAction = new QAction(tr("Close"));
    MenuFromButton->addSeparator();
    MenuFromButton->addAction(closeAction);

    QMenu* menuTheme = new QMenu;
    menuTheme->addAction(lightAction);
    menuTheme->addAction(darkAction);
    themeMenu->setMenu(menuTheme);

    Menu->setMenu(MenuFromButton);

    resultLabel = new QLabel("0");
    resultLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    resultLabel->setFont(fontLabel);
    resultLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
    gridlayout->addWidget(resultLabel, 1, 0, 1, 4);

    percent = new QPushButton("%");
    percent->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    percent->setFont(fontButton);
    gridlayout->addWidget(percent, 2, 0);

    plus_minus = new QPushButton("+/-");
    plus_minus->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    plus_minus->setFont(fontButton);
    gridlayout->addWidget(plus_minus, 2, 1);

    Button_C = new QPushButton("C");
    Button_C->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    Button_C->setFont(fontButton);
    gridlayout->addWidget(Button_C, 2, 2);

    Button_DeleteLastNumber = new QPushButton("⌫");
    Button_DeleteLastNumber->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    Button_DeleteLastNumber->setFont(fontButton);
    gridlayout->addWidget(Button_DeleteLastNumber, 2, 3);

    oneDivisionX = new QPushButton("1/x");
    oneDivisionX->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    oneDivisionX->setFont(fontButton);
    gridlayout->addWidget(oneDivisionX, 3, 0);

    square_degree = new QPushButton("x²");
    square_degree->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    square_degree->setFont(fontButton);
    gridlayout->addWidget(square_degree, 3, 1);

    square_root = new QPushButton("√x");
    square_root->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    square_root->setFont(fontButton);
    gridlayout->addWidget(square_root, 3, 2);

    division = new QPushButton("÷");
    division->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    division->setFont(fontButton);
    gridlayout->addWidget(division, 3, 3);

    number_7 = new QPushButton("7");
    number_7->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    number_7->setFont(fontButton);
    gridlayout->addWidget(number_7, 4, 0);

    number_8 = new QPushButton("8");
    number_8->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    number_8->setFont(fontButton);
    gridlayout->addWidget(number_8, 4, 1);

    number_9 = new QPushButton("9");
    number_9->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    number_9->setFont(fontButton);
    gridlayout->addWidget(number_9, 4, 2);

    multiplication = new QPushButton("×");
    multiplication->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    multiplication->setFont(fontButton);
    gridlayout->addWidget(multiplication, 4, 3);

    number_4 = new QPushButton("4");
    number_4->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    number_4->setFont(fontButton);
    gridlayout->addWidget(number_4, 5, 0);

    number_5 = new QPushButton("5");
    number_5->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    number_5->setFont(fontButton);
    gridlayout->addWidget(number_5, 5, 1);

    number_6 = new QPushButton("6");
    number_6->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    number_6->setFont(fontButton);
    gridlayout->addWidget(number_6, 5, 2);

    minus = new QPushButton("-");
    minus->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    minus->setFont(fontButton);
    gridlayout->addWidget(minus, 5, 3);

    number_1 = new QPushButton("1");
    number_1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    number_1->setFont(fontButton);
    gridlayout->addWidget(number_1, 6, 0);

    number_2 = new QPushButton("2");
    number_2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    number_2->setFont(fontButton);
    gridlayout->addWidget(number_2, 6, 1);

    number_3 = new QPushButton("3");
    number_3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    number_3->setFont(fontButton);
    gridlayout->addWidget(number_3, 6, 2);

    plus = new QPushButton("+");
    plus->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    plus->setFont(fontButton);
    gridlayout->addWidget(plus, 6, 3);

    number_0 = new QPushButton("0");
    number_0->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    number_0->setFont(fontButton);
    gridlayout->addWidget(number_0, 7, 0, 1, 2);

    Button_Point = new QPushButton(".");
    Button_Point->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    Button_Point->setFont(fontButton);
    gridlayout->addWidget(Button_Point, 7, 2);

    Button_Equal = new QPushButton("=");
    Button_Equal->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    Button_Equal->setFont(fontButton);
    Button_Equal->setStyleSheet("QPushButton { background-color: #023e8a; }");
    gridlayout->addWidget(Button_Equal, 7, 3);

}

void Calculator::setup()
{
    plus->setCheckable(true);
    minus->setCheckable(true);
    multiplication->setCheckable(true);
    division->setCheckable(true);
}

void Calculator::connecting()
{
    connect(number_0, &QPushButton::clicked, this, &Calculator::connectNumbers);
    connect(number_1, &QPushButton::clicked, this, &Calculator::connectNumbers);
    connect(number_2, &QPushButton::clicked, this, &Calculator::connectNumbers);
    connect(number_3, &QPushButton::clicked, this, &Calculator::connectNumbers);
    connect(number_4, &QPushButton::clicked, this, &Calculator::connectNumbers);
    connect(number_5, &QPushButton::clicked, this, &Calculator::connectNumbers);
    connect(number_6, &QPushButton::clicked, this, &Calculator::connectNumbers);
    connect(number_7, &QPushButton::clicked, this, &Calculator::connectNumbers);
    connect(number_8, &QPushButton::clicked, this, &Calculator::connectNumbers);
    connect(number_9, &QPushButton::clicked, this, &Calculator::connectNumbers);

    connect(plus, &QPushButton::clicked, this, &Calculator::connectMathOperations);
    connect(minus, &QPushButton::clicked, this, &Calculator::connectMathOperations);
    connect(multiplication, &QPushButton::clicked, this, &Calculator::connectMathOperations);
    connect(division, &QPushButton::clicked, this, &Calculator::connectMathOperations);

    connect(Button_Equal, &QPushButton::clicked, this, [&]()
    {
        double numSecond;
        double resultNumber;
        QString resultText;
        numSecond = resultLabel->text().toDouble();

        if(plus->isChecked())
        {
            resultNumber = numFirst + numSecond;
            resultText = QString::number(resultNumber, 'g', 15);
            resultLabel->setText(resultText);
            plus->setChecked(false);
        }
        else if(minus->isChecked())
        {
            resultNumber = numFirst - numSecond;
            resultText = QString::number(resultNumber, 'g', 15);
            resultLabel->setText(resultText);
            minus->setChecked(false);
        }
        else if(multiplication->isChecked())
        {
            resultNumber = numFirst * numSecond;
            resultText = QString::number(resultNumber, 'g', 15);
            resultLabel->setText(resultText);
            multiplication->setChecked(false);
        }
        else if(division->isChecked())
        {
            if(numSecond != 0)
            {
                resultNumber = numFirst / numSecond;
                resultText = QString::number(resultNumber, 'g', 15);
                resultLabel->setText(resultText);
                division->setChecked(false);
            }
            else
            {
                resultLabel->setText(tr("division by zero is not possible"));
                division->setChecked(false);
            }
        }
    });

    connect(Button_C, &QPushButton::clicked, this, [&]()
    {
        resultLabel->setText("0");
        plus->setChecked(false);
        minus->setChecked(false);
        multiplication->setChecked(false);
        division->setChecked(false);
    });

    connect(percent, &QPushButton::clicked, this, &Calculator::connectAdditionalOperations);
    connect(plus_minus, &QPushButton::clicked, this, &Calculator::connectAdditionalOperations);
    connect(oneDivisionX, &QPushButton::clicked, this, &Calculator::connectAdditionalOperations);
    connect(square_degree, &QPushButton::clicked, this, &Calculator::connectAdditionalOperations);
    connect(square_root, &QPushButton::clicked, this, &Calculator::connectAdditionalOperations);

    connect(Button_DeleteLastNumber, &QPushButton::clicked, this, [&]()
    {
        QString number = resultLabel->text();
        if(number.size() == 1)
        {
            resultLabel->setText("0");
        }
        else
        {
            number.chop(1);
            resultLabel->setText(number);
        }
    });

    connect(Button_Point, &QPushButton::clicked, this, [&]()
    {
        if(!resultLabel->text().contains('.'))
        {
            resultLabel->setText(resultLabel->text() + ".");
        }

    });

    connect(lightAction, &QAction::triggered, this, &Calculator::connectMenuActions);
    connect(darkAction, &QAction::triggered, this, &Calculator::connectMenuActions);
    connect(closeAction, &QAction::triggered, this, &QApplication::quit);
}

void Calculator::LightTheme()
{
    QPalette lightPalette;

    lightPalette.setColor(QPalette::Window, Qt::white);
    lightPalette.setColor(QPalette::Button, Qt::white);
    lightPalette.setColor(QPalette::ButtonText, Qt::black);
    Menu->setStyleSheet("QPushButton { background-color: transparent; border: 0px; color: black; }"
                        "QPushButton:hover { background-color: #dddfdf; color: black; }");
    resultLabel->setStyleSheet("QLabel { color: black; }");

    plus->setStyleSheet("QPushButton { background-color: white; color: black; }");
    minus->setStyleSheet("QPushButton { background-color: white; color: black; }");
    multiplication->setStyleSheet("QPushButton { background-color: white; color: black; }");
    division->setStyleSheet("QPushButton { background-color: white; color: black; }");
    square_root->setStyleSheet("QPushButton { background-color: white; color: black; }");
    square_degree->setStyleSheet("QPushButton { background-color: white; color: black; }");
    oneDivisionX->setStyleSheet("QPushButton { background-color: white; color: black; }");
    Button_DeleteLastNumber->setStyleSheet("QPushButton { background-color: white; color: black; }");
    Button_C->setStyleSheet("QPushButton { background-color: white; color: black; }");
    plus_minus->setStyleSheet("QPushButton { background-color: white; color: black; }");
    percent->setStyleSheet("QPushButton { background-color: white; color: black; }");

    qApp->setPalette(lightPalette);
}

void Calculator::DarkTheme()
{
    QPalette darkPalette;

    darkPalette.setColor(QPalette::Window, QColor(53, 53, 53));
    darkPalette.setColor(QPalette::Button, QColor(53, 53, 53));
    darkPalette.setColor(QPalette::ButtonText, Qt::white);
    Menu->setStyleSheet("QPushButton { background-color: transparent; border: 0px; color: white; }"
                        "QPushButton:hover { background-color: #595959; color: white; }");
    resultLabel->setStyleSheet("QLabel { color: white; }");

    plus->setStyleSheet("QPushButton { background-color: #282828; color: white; }");
    minus->setStyleSheet("QPushButton { background-color: #282828; color: white; }");
    multiplication->setStyleSheet("QPushButton { background-color: #282828; color: white; }");
    division->setStyleSheet("QPushButton { background-color: #282828; color: white; }");
    square_root->setStyleSheet("QPushButton { background-color: #282828; color: white; }");
    square_degree->setStyleSheet("QPushButton { background-color: #282828; color: white; }");
    oneDivisionX->setStyleSheet("QPushButton { background-color: #282828; color: white; }");
    Button_DeleteLastNumber->setStyleSheet("QPushButton { background-color: #282828; color: white; }");
    Button_C->setStyleSheet("QPushButton { background-color: #282828; color: white; }");
    plus_minus->setStyleSheet("QPushButton { background-color: #282828; color: white; }");
    percent->setStyleSheet("QPushButton { background-color: #282828; color: white; }");

    qApp->setPalette(darkPalette);
}

void Calculator::keyPressEvent(QKeyEvent *event)
{
    QString oldText = resultLabel->text();
    int key = event->key();
    QString str = static_cast<QString>(QChar(key));
    if(key >= Qt::Key_0 && key <= Qt::Key_9)
    {
        if (oldText.contains('.'))
        {
            QStringList parts = oldText.split('.');
            if (parts.size() > 1 && parts[1].size() >= 15) {
                return;
            }
        }

        if(oldText == "0")
        {
            oldText.clear();
        }
        resultLabel->setText(oldText + str);
    }
    else if(key == Qt::Key_Backspace)
    {
        if(oldText.size() == 1)
        {
            resultLabel->setText("0");
        }
        else
        {
            oldText.chop(1);
            resultLabel->setText(oldText);
        }
    }
}

void Calculator::connectNumbers()
{
    QPushButton* button = qobject_cast<QPushButton*>(sender());
    QString numberLabel = resultLabel->text();

    if (numberLabel.contains('.'))
    {
        QStringList parts = numberLabel.split('.');
        if (parts.size() > 1 && parts[1].size() >= 15) {
            return;
        }
    }

    if (numberLabel == "0") {
        numberLabel.clear();
    }
    numberLabel += button->text();

    resultLabel->setText(numberLabel);
}

void Calculator::connectMathOperations()
{
    QPushButton* button = qobject_cast<QPushButton*>(sender());
    numFirst = resultLabel->text().toDouble();
    resultLabel->setText("");
    button->setChecked(true);
}

void Calculator::connectAdditionalOperations()
{
    QPushButton* button = qobject_cast<QPushButton*>(sender());
    QString textOnButton = button->text();
    QString numberOnLabel = resultLabel->text();
    double result = numberOnLabel.toDouble();

    if(textOnButton == "%")
    {
        result *= 0.01;
        resultLabel->setText(QString::number(result, 'g', 15));
    }
    else if(textOnButton == "+/-")
    {
        result *= -1;
        resultLabel->setText(QString::number(result, 'g', 15));
    }
    else if(textOnButton == "1/x")
    {
        if(result != 0)
        {
            result = 1 / result;
            resultLabel->setText(QString::number(result, 'g', 15));
        }
        else
        {
            resultLabel->setText(tr("division by zero is not possible"));
        }
    }
    else if(textOnButton == "x²")
    {
        result = std::pow(result, 2);
        resultLabel->setText(QString::number(result, 'g', 15));
    }
    else if(textOnButton == "√x")
    {
        result = std::sqrt(result);
        resultLabel->setText(QString::number(result, 'g', 15));
    }
}

void Calculator::connectMenuActions()
{
    QAction* action = qobject_cast<QAction*>(sender());

    if(action->data() == 1)
    {
        LightTheme();
    }
    else if(action->data() == 2)
    {
        DarkTheme();
    }
}
